	title	NAME.LDD device driver for S3/S3a/S3c/S3../HC
	subttl	Copyright PSION PLC November 1995
	name	NAME

;	VERSION   DATE     DESCRIPTION
;	------- -------- ---------------
;	  1.0   12/01/95 Template LDD

;	Written by Jason Robinson January 1995

BUILDSB	equ	1

        include ..\inc\epoc.inc
        include ..\inc\epocser.inc
        include ..\inc\epoclib.inc
        include ..\inc\epocsibo.inc
        include ..\srcs\ossibo.inc
	include ..\srcs\ospack.inc
	
        OpenSpecificChannel     =0
        MachineSpecific         =0
        PeripheralTypeDriver    =0
        TickRequired            =0

        NumberOfChannels        equ     1
        WeSupportS3Only         equ     Lcd240X80
        WeSupportS3aOnly        equ     Lcd480X160
        WeSupportS3cOnly        equ     Lcd240X100
        WeSupportHCOnly         equ     Lcd160X80
        TheMachineWeSupport     equ     WeSupportS3aOnly

TmpltEnt struc
        TmpltEntOpen            db      ?       ; Channel open flag
        TmpltChannelStarted     db      ?       ; Channel should be running
        TmpltChannelRunning     db      ?       ; Can channel really run
        TmpltSpare              db      ?
        TmpltHwChannel          dw      ?       ; The harware we want
        TmpltStructPtr          dw      ?       ; Ptr to CB in Apps DS
if      PeripheralTypeDriver or TickRequired
        TmpltTckHandle          dw      ?       ; Tick Handle
endif
TmpltEnt ends

TmpltStruct struc
        Tmpltblk		ChanEnt <>      ; I/O control block
        TmpltEntPtr             dw      ?       ; Ptr to our CS CB
TmpltStruct ends

	dgroup group stack
	assume ds:dgroup,es:dgroup,ss:dgroup

	CodeSeg
	
	ProcBegin@ TmpltLDD
;	===================

	dw	LDDSignature
	db	'HSB',0,0,0,0,0
	dw	(TableEnd-TableStart)/2
TableStart:
	dw	TmpltInstall
	dw	TmpltRemove
	dw	TmpltHold
	dw	TmpltResume
        dw      TmpltReset
        dw      TmpltUnits
        dw      TmpltOpen
        dw      TmpltStrategy
if      PeripheralTypeDriver or TickRequired
MonitorVector:
        dw      MonitorInt
endif
TableEnd:
	
	CsHeldFlag	db	0			; Ldd under a hold?
        MachineType     db      0

        Channel0        TmpltEnt <>
			
	ProcEnd noret

	ProcBegin@ TmpltInstall,far
;	===========================

;	Install the driver
;	Exit with carry clear for okay

if      MachineSpecific
	GenLcdType                                      ; Do we only run on
        mov     MachineType,al                          ; particular machines?
        cmp     al,TheMachineWeSupport
        jne     CannotInstallOnThisMachine
endif
	mov	CsHeldFlag,0				; Initialise all
        mov     cx,NumberOfChannels                     ; the variables
        mov     di,offset Channel0
        xor     ax,ax
ResetAllChannelsLoop:
        mov     cs:[di].TmpltEntOpen,al
        add     di,size TmpltEnt
        loop    ResetAllChannelsLoop
FinishedOkay:						
	clc						
	ret
CannotInstallOnThisMachine:
        mov     ax,NotSupportedErr
        stc
        ret						
	ProcEnd noret

	ProcBegin@ TmpltRemove,far
;	==========================

;	Remove the driver
;	Exit with carry clear for okay
;	Exit with carry set if channel still open

        mov     cx,NumberOfChannels
        mov     di,offset Channel0
        xor     ax,ax
CheckAllChannelsClosedLoop:
        cmp     cs:[di].TmpltEntOpen,al
        jne     WeHaveAnOpenChannelSoFail
        add     di,size TmpltEnt
        loop    CheckAllChannelsClosedLoop
        jmp     FinishedOkay
WeHaveAnOpenChannelSoFail:
	mov 	ax,InUseErr
	stc
	ret
	ProcEnd noret

	ProcBegin@ TmpltUnits,far
;	=========================

;	Return the Number of channels that can be opened in AX

	mov	ax,NumberOfChannels     		; We have ? channels
	ret
	ProcEnd noret

	ProcBegin@ TmpltReset,far
;	=========================

;	Reset the open channel

        mov     di,cx
	cmp	cs:[di].TmpltEntOpen,0			; Somethings gone
	je	NotOpenToReset				; wrong with the
        mov     ah,DevHoldPowerDown                     ; application that 
	call	StopTheChannel				; opened us.
        call    FreeHardware                            ; Stop interupts and
	mov	cs:[di].TmpltEntOpen,0			; free the channel 
NotOpenToReset:						
	ret						
	ProcEnd noret

	ProcBegin@ TmpltHold,far
;	========================
	
;	Hold the channels
;       Hold reason in AH

	mov	cx,1
	xchg	cl,CsHeldFlag				; Stop any interrupts
	cmp	cl,0					; Mark channel as
	jne	AlreadyHeld				; under a normal hold
DoHold:
        mov     cx,NumberOfChannels
        mov     di,offset Channel0
HoldAllTheChannelsLoop:
        cmp     cs:[di].TmpltEntOpen,0
        je      DontHoldBecauseNotOpen
        cmp     cs:[di].TmpltChannelStarted,0
        je      DontHoldBecauseNotOpen
        push    ax
        push    cx
	call	StopTheChannel
        pop     cx
        pop     ax
DontHoldBecauseNotOpen:
        add     di,size TmpltEnt
        loop    HoldAllTheChannelsLoop
AlreadyHeld:
	ret
	ProcEnd noret

	ProcBegin@ TmpltResume,far
;	==========================

;	Resume the channel

	xor	cx,cx					; Be warned during an
	xchg	cl,CsHeldFlag				; on/off the power to
	cmp	cl,0					; ASIC4 is not restored
	je	AlreadyResumed				; until after this
if      PeripheralTypeDriver
	GenDataSegment		 			; A resume is pointless
	HwGetSsdData					; if there is still no
	mov	bx,ax					; power to the port
	cmp	es:[bx].SsdDoorStatus,DoorOpen		; Leave the resume
	je	DoorsAreOpen				; to the tick
endif
DoResume:
        mov     cx,NumberOfChannels
        mov     di,offset Channel0                      ; Right hardware?
ResumeAllTheChannelsLoop:                               ; Else restart
        cmp     cs:[di].TmpltEntOpen,0                  ; interrupts    
        je      DontResumeBecauseNotOpen
        cmp     cs:[di].TmpltChannelStarted,0
        je      DontResumeBecauseNotOpen
        push    cx
	call	StartTheChannel
        pop     cx
DontResumeBecauseNotOpen:
        add     di,size TmpltEnt
        loop    ResumeAllTheChannelsLoop
AlreadyResumed:						
	ret
if      PeripheralTypeDriver
DoorsAreOpen:
	mov	CsHeldFlag,2
	ret
endif
	ProcEnd noret

	ProcBegin@ TmpltOpen,far
;	========================

;	Open the channel
;	DS,ES,SS Applications data space
;	Handle in DX

	cld
        pushf
        cli
        call    FindFreeChannel
        jnc     GotFreeChannel
        popf
LockedError:
	mov	ax,LockedErr
	stc
	ret
AllErrorsExitHere:
        push    ax
	HeapFreeCell
        pop     ax
FreeTckAndChannel:
        push    ax
        call    FreeHardware
        pop     ax
FreeTckAndExit:
if      PeripheralTypeDriver or TickRequired
        push    ax
        mov	bx,cs:[di].TmpltTckHandle
	IoClose
        pop     ax
endif
CloseThenFree:
	mov	cs:[di].TmpltEntOpen,0
	stc
	ret
GotFreeChannel:
	mov	cs:[di].TmpltEntOpen,1
        mov     cs:[di].TmpltChannelStarted,0
        mov     cs:[di].TmpltChannelRunning,0
	popf
if      PeripheralTypeDriver or TickRequired
	xor	ax,ax
	push	ax
	mov	ax,((':' shl 8)+'K')
	push	ax
	mov	ax,(('C' shl 8)+'T')
	push	ax
	mov	bx,sp
	IoOpen
	jnc	GotATickChannel
	add	sp,6
	mov	ax,LockedErr
	jmp	CloseThenFree
GotATickChannel:
	add	sp,6
	mov	cs:[di].TmpltTckHandle,ax
	push	dx
	mov	bx,ax
	mov	ax,IoFuncStart
	mov	cx,1
	push	cx                                      ; Frequency 1 tick
	push	di                                      ; Data is our CS CB
	push	dx                                      ; Our device handle
	mov	cx,(MonitorVector-TableStart)/2         ; Vector to call
	push	cx
	mov	cx,sp
	IoWithWait
	add	sp,8
	pop	dx
endif
        call    GetHardware
	jc 	FreeTckAndExit

	mov	cx,(size TmpltStruct)			; Get ourselfs a CB
	HeapAllocateCell				; In the applications
	jc	FreeTckAndChannel			; Data space

	mov	bx,ax
     	mov	[bx].Tmpltblk.ChanNext,bx
	mov	[bx].Tmpltblk.ChanSignature,IoChanSignature
	mov	[bx].Tmpltblk.ChanLibHandle,dx
	mov	[bx].TmpltEntPtr,di
        push    bx
        mov     bx,dx
	mov	cx,di
	IoRequestReset
        pop     bx
	xor     ax,ax
	ret
	ProcEnd noret

StrategyVectorTable label word
        dw      offset StrategyDefault
        dw      offset StrategyDefault
        dw      offset StrategyDefault
        dw      offset TmpltClose
        dw      offset StrategyDefault
        dw      offset StrategyDefault
        dw      offset StrategyDefault
        dw      offset StrategyDefault
        dw      offset StrategyDefault
        dw      offset StrategyDefault
        dw      offset StrategyDefault
        dw      offset StrategyDefault
        dw      offset StrategyDefault
        dw      offset StrategyDefault

	ProcBegin@ TmpltStrategy,far
;	============================

;	BX is our control block
;	SI points to the parameters
;	DS,ES Applications data space

	mov	ax,[si].RqFunction
	mov	dx,[si].RqA1Ptr
	cmp	ax,IoFuncSuperFrame
	ja	StrategyDefault
	shl	ax,1
	mov	di,ax
	push	StrategyVectorTable[di]
	mov	di,[bx].TmpltEntPtr
        retn
StrategyDefault:
	IoRoot
	ret
ExitStrategyOkay:
        xor     ax,ax
ExitStrategy:
	mov	di,[si].RqStatusPtr
	mov	word ptr [di],ax
        cmp     ax,PendingErr
        je      JustExit
	IoSignal
JustExit:
	xor	ax,ax
	ret
	ProcEnd noret

	ProcBegin@ TmpltClose,far
;	=========================

;	Close a channel
;	DI CS control block
;       BX DS control block
;       SI points to aurguments on stack
;	DX Argument one pointer

        mov     ah,DevHoldPowerDown
	call	StopTheChannel
        call    FreeHardware
        push    bx
	mov	bx,[bx].Tmpltblk.ChanLibHandle
	mov     cx,di
        IoRequestResetCancel
        pop     bx
	HeapFreeCell
if      PeripheralTypeDriver or TickRequired
        mov	bx,cs:[di].TmpltTckHandle
	IoClose
endif
	mov	cs:[di].TmpltEntOpen,0
        jmp     short ExitStrategyOkay
	ProcEnd noret

	ProcBegin@ StartTheChannel
;	==========================

;       Start the Channel Running
	
        cmp     byte ptr cs:[di].TmpltChannelRunning,0
        jne     ChannelAlreadyRunning

        mov     cs:[di].TmpltChannelRunning,1
ChannelAlreadyRunning:
        clc
        ret
        ProcEnd noret

	ProcBegin@ StopTheChannel
;	=========================

;       Stop the Channel Running

        cmp     byte ptr cs:[di].TmpltChannelRunning,0
        je      ChannelAlreadyStopped

        mov     cs:[di].TmpltChannelRunning,0
ChannelAlreadyStopped:
        clc
        ret
        ProcEnd noret

	ProcBegin@ GetHardware
;	======================

        clc
        ret
        ProcEnd noret

	ProcBegin@ FreeHardware
;	=======================

        clc
        ret
        ProcEnd noret

If      OpenSpecificChannel
	ProcBegin@ FindFreeChannel
;	==========================

;       Called from Open
;       Must preserve DX,SI
;       Channel out in DI or carry set if failure

	mov	si,[si].OpenNamePtr
	mov	al,[si+1]
        CharToFoldedChar
	cmp	al,'A'
	jb	CantGetThatChannel
	sub	al,'A'
	cmp	al,NumberOfChannels
	jae	CantGetThatChannel
        xor     ah,ah
        push    dx
        mov     dx,size TmpltEnt
        mul     dx
        pop     dx
        mov     di,ax
        add     di,offset Channel0
        cmp     cs:[di].TmpltEntOpen,0
        je      FoundAFreeChannel
CantGetThatChannel:
        stc
        ret
FoundAFreeChannel:
        clc
        ret
        ProcEnd noret
else
	ProcBegin@ FindFreeChannel
;	==========================

        mov     cx,NumberOfChannels
        mov     di,offset Channel0
HuntAllChannelsLoop:
        cmp     cs:[di].TmpltEntOpen,0
        je      FoundAFreeChannel
        add     di,size TmpltEnt
        loop    HuntAllChannelsLoop
        stc
        ret
FoundAFreeChannel:
        clc
        ret
        ProcEnd noret
endif

if      PeripheralTypeDriver or TickRequired
	ProcBegin@ MonitorInt,far
;	=========================

if      PeripheralTypeDriver
;       Called on every tick
;       Issues pack door hold and resumes
;       In:  Door state in SI

	cmp	si,DoorOpen
        je      TheDoorIsOpenSoCantDoAnything
	cmp	CsHeldFlag,2
        je      NeedToDoTheResume
        ret
NeedToDoTheResume:
	mov	CsHeldFlag,0
        jmp     DoResume
TheDoorIsOpenSoCantDoAnything:
	cmp	CsHeldFlag,0
        jne     DontNeedToHold
	mov	CsHeldFlag,2
        mov     ah,DevHoldPowerFail
        jmp     DoHold
DontNeedToHold:
endif
        ret
        ProcEnd noret
endif

	EndCodeSeg
	stack segment stack para 'data'
	stack ends
	end TmpltLDD













